# 异常章节
"""
1. 什么是异常
当检测到一个错误时，Python解释器无法继续执行了，反而出现了一些错误提示,
这就是所谓的异常，也就是常说的BUG
"""
# 异常演示: 读取一个不存在的文件
# fr = open("hello.txt", "r", encoding="UTF-8")

# 2. 异常的捕获
# 2.1 为什么要捕获异常
'''
世界上没有完美的程序, 任何程序在运行的时候都可能出现异常
而我们要做的不是力求程序能够完美运行, 而是对可能出现的bug进行提前处理、提前准备
这种行为称之为异常处理(捕获异常)

当程序遇到bug，有两种情况:
1. 整个程序因为bug而停止运行
2. 对bug进行提醒而不停止运行

捕获异常的作用在于: 提前假设某处会出现异常, 做好提前准备, 当真的出现异常的时候, 可以有后续手段
'''

# 三、 捕获常规异常
"""
基本语法
try:
    可能发生错误的代码
except:
    出现异常所需执行的代码
"""
# 除0错误
try:
    a = 1 / 0
except:
    print("除0错误")

# 四、捕获指定异常
"""
语法格式:
try: 
    可能发生错误的代码
except 异常的类型 as 异常别名:
    出现异常所需执行的代码
"""
try:
    print(name)
    # 1 / 0 # 无法捕获
except NameError as e: # 我这里指定捕获变量名未定义的异常，如果try中出现别的异常，是无法被except捕获的
    print(e) # e记录着异常的具体信息

# 五、捕获多个异常
"""
当捕获多个异常时，可以要把捕获的异常类型名字放在except后，并使用元组的方式进行书写
try:
    可能发生错误的代码1
    可能发生错误的代码2
    ...
except (异常类型1, 异常类型2, ... ) as xx:
    出现异常所需执行的代码
"""
try:
    a = 1 / 0
    print(b)
except (ZeroDivisionError, NameError) as e:
    print(e)

print("==============================")

# 六、捕获所有异常
"""
基本语法
try:
    可能发生错误的代码
except: # 无类型，不能对异常对象进行重命名
    出现异常所需执行的代码
    
or

# 常用
try:
    可能发生错误的代码
except Exception as e:
    出现异常所需执行的代码
"""

# 七、异常else（可选）
"""
else表示的是如果没有出现异常所要执行的代码

基本语法:
try:
    可能发生错误的代码
except Exception as e:
    出现异常所需执行的代码
else:
    没有出现异常所要执行的代码
"""

# 八、异常的finally（可选）
"""
finally表示的是无论是否有异常都要执行的代码
try:
    可能发生错误的代码
except Exception as e:
    出现异常所需执行的代码
finally:
    没异常也要执行,有异常也要执行
"""

# 八、异常的传递
"""
异常具有传递性
"""
def func01():
    print("def func01()::begin")
    num = 1 / 0
    print("def func01()::end")

def func02():
    print("def func02()::begin")
    func01()
    print("def func02()::end")

def main():
    try:
        func02()
    except Exception as e:
        print(e)

main()

# 当函数func01中发生异常，并且没有捕获处理这个异常的时候，异常会传递到函数func02
# 当函数func02也没有捕获这个异常的时候，main函数会捕获这个异常
#  注意: 当所有函数都没捕获到异常的时候，程序就会报错